/**
 * org.assess.core.common.StringUtils
 */
package org.assess.core.common;

import java.io.UnsupportedEncodingException;
import java.util.Arrays;
import java.util.regex.Pattern;

/**
 * @description String Util Collection
 * @author XiaLongxiang
 * @createtime 2011-12-14 上午10:29:04
 */
public final class StringUtils {
    /**
     * 按指定byte长度截断字符串，对于非ASCII格式的字符将不会被截断 仅支持UTF-8格式
     * @param s
     * @param size
     * @return
     */
    public static String substring(String str, int size) {
        if (size <= 0) {
            return "";
        }
        else if (str == null || str.getBytes().length <= size) {
            return str;
        }
        
        int index = 0;
        byte[] bs = str.getBytes();
        if ((bs[size] >> 7) == 0x0 || ((bs[size] >> 6) & 0x03) == 0x03) {
            index = size;
        }
        else {
            for (int i = size - 1; i >= 0; i--) {
                if (((bs[i] >> 6) & 0x03) == 0x03) {
                    index = i;
                    break;
                }
            }
        }
        return new String(Arrays.copyOf(str.getBytes(), index));
    }
    
    /**
     * 通过使用指定的 charset 解码指定的 byte 数组，构造一个新的 String
     * @param bytes
     * @param charsetName
     * @return
     */
    public static String newString(byte[] bytes, String charsetName) {
        try {
            return new String(bytes, charsetName);
        }
        catch (UnsupportedEncodingException e) {
            return null;
        }
    }
    
    /**
     * 通过使用指定的字符集解码指定的 byte 子数组，构造一个新的 String
     * @param bytes
     * @param offset
     * @param length
     * @param charsetName
     * @return
     */
    public static String newString(byte[] bytes, int offset, int length, String charsetName) {
        try {
            return new String(bytes, offset, length, charsetName);
        }
        catch (UnsupportedEncodingException e) {
            return null;
        }
    }
    
    /**
     * 将普通的文本字符串转换成16进制字符串
     * @param str
     * @param space
     * @return
     */
    public static String parse16(String str, boolean space) {
        return parse16(str.getBytes(), space);
    }
    
    /**
     * 将byte数组转换成16进制字符串，如数组{0x78, 0x2A, 0x5C}将转换成字符串"78 2A 5C"
     * @param data
     * @param space 是否携带空格即显示形式是"782A5C"还是"78 2A 5C"
     * @return
     */
    public static String parse16(byte[] data, boolean space) {
        if (data == null || data.length == 0) {
            return null;
        }
        
        StringBuffer buf = new StringBuffer();
        for (int i = 0; i < data.length; i++) {
            byte b = data[i];
            buf.append(GeneralUtils.digits[(b >>> 4) & 0x0f]);
            buf.append(GeneralUtils.digits[b & 0x0f]);
            if (space) {
                buf.append(" ");
            }
        }
        
        // 如果是以空格为结尾，则删除此空格
        if (buf.lastIndexOf(" ") == buf.length() - 1) {
            buf.delete(buf.length() - 1, buf.length());
        }
        return buf.toString();
    }
    
    /**
     * 将16进制文本字符串转换成普通字符串
     * @param hex
     * @return
     */
    public static String hex2String(String hex) {
        Pattern pattern = Pattern.compile("^0(x|X)");
        boolean find = pattern.matcher(hex).find();
        if (find) {
            hex = hex.substring(2);
        }
        hex = hex.replaceAll("\\s", "");
        
        char[] chs = hex.toCharArray();
        byte[] bytes = new byte[hex.length() / 2];
        for (int i = 0; i < bytes.length; i++) {
            bytes[i] = (byte) (char2byte(chs[i * 2]) << 4 | char2byte(chs[i * 2 + 1]));
        }
        return new String(bytes);
    }
    
    /**
     * 将long型转换成16进制表现形式
     * @param num
     * @param pix - 是否带0x前缀
     * @return
     */
    public static String parse16(long num, boolean pix) {
        return parse16(num, 16, pix);
    }
    
    /**
     * 将int型转换成16进制表现形式
     * @param num
     * @param pix - 是否带0x前缀
     * @return
     */
    public static String parse16(int num, boolean pix) {
        return parse16(num, 8, pix);
    }
    
    /**
     * 将short型转换成16进制表现形式
     * @param num
     * @param pix - 是否带0x前缀
     * @return
     */
    public static String parse16(short num, boolean pix) {
        return parse16(num, 4, pix);
    }
    
    /**
     * 将byte型转换成16进制表现形式
     * @param num
     * @param pix - 是否带0x前缀
     * @return
     */
    public static String parse16(byte num, boolean pix) {
        return parse16(num, 2, pix);
    }
    
    /**
     * 将数值转换成指定长度的16进制表现形式
     * @param num
     * @param index
     * @param pix - 是否带0x前缀
     * @return
     */
    public static String parse16(long num, int index, boolean pix) {
        char[] chs;
        if (pix) {
            chs = new char[index + 2];
            chs[0] = '0';
            chs[1] = 'x';
            for (int i = index - 1; i >= 0; i--) {
                int _t = (int) (num >>> (i * 4) & 0x0f);
                chs[index + 1 - i] = GeneralUtils.digits[_t];
            }
        }
        else {
            chs = new char[index];
            for (int i = index - 1; i >= 0; i--) {
                int _t = (int) (num >>> (i * 4) & 0x0f);
                chs[index - 1 - i] = GeneralUtils.digits[_t];
            }
        }
        return new String(chs);
    }
    
    /**
     * 将16进制的char字符转换成byte
     * @param ch
     * @return
     */
    private static byte char2byte(char ch) {
        int result = "0123456789ABCDEF".indexOf(Character.toUpperCase(ch));
        if (result == -1) {
            throw new RuntimeException("Unable transport char \"" + ch + "\"to Hex byte");
        }
        
        return (byte) result;
    }
    
    public static void main(String... args) {
        // System.out.println(hex2String("0xE4BDA0E5A5BDE5909761615A5A"));
        System.out.println(hex2String(parse16("acccddfaZ你好吗？", false)));
        
        String hex = "fda 你哦号\nfdd fd\radd  ifda\r\nf   da";
        System.out.println(hex.replaceAll("\\s", ""));
    }
    
    /**
     * <私有构造方法>
     */
    private StringUtils() {
        
    }
}
